package com.appbee.songs.client.presenter.impl;

import java.util.List;

import javax.inject.Inject;

import com.appbee.core.client.data.BufferedDataProvider;
import com.appbee.core.client.data.IDataUpdater;
import com.appbee.core.client.data.IFetcher;
import com.appbee.core.client.data.ISortInfo;
import com.appbee.core.client.data.SimpleSortInfo;
import com.appbee.core.client.place.EditPlace;
import com.appbee.core.client.place.PlaceControl;
import com.appbee.songs.client.SongActivityModul;
import com.appbee.songs.client.presenter.ISongsDataPresenter;
import com.appbee.songs.client.ui.ISongFilterView;
import com.appbee.songs.client.ui.ISongsView;
import com.appbee.songs.client.ui.SongEditColumn;
import com.appbee.songs.client.ui.SortableColumn;
import com.appbee.songs.shared.FilterField;
import com.appbee.songs.shared.SongFilterProxy;
import com.appbee.songs.shared.SongProxy;
import com.appbee.songs.shared.SongRequestFactory;
import com.appbee.songs.shared.SongServiceRequest;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;
import com.google.web.bindery.requestfactory.shared.Receiver;

public class SongsDataPresenter implements
		ISongsDataPresenter
{
	private ISongsView view;
	private final SongRequestFactory serviceProvider;
	private int viewSize = 15;
	private final PlaceControl placeController;
	private DataProvider dataProvider;
	private SimpleSortInfo currentSortInfo = null;
	private final SongActivityModul activityModul;
	
	@Inject
	public SongsDataPresenter(	SongActivityModul activityModul,
							SongRequestFactory serviceProvider,
							PlaceControl placeController)
	{
		this.activityModul = activityModul;
		this.serviceProvider = serviceProvider;
		this.placeController = placeController;
	}

	public int getViewSize()
	{
		return viewSize;
	}

	public void setViewSize(int viewSize)
	{
		this.viewSize = viewSize;
	}

	public void setView(ISongsView view)
	{
		this.view = view;
		view.setPresenter(this);
		view.getDataDisplay().setVisibleRangeAndClearData(	new Range(0,
																	viewSize),
															true);

	}

	public void start()
	{
		this.dataProvider = new DataProvider(view.getFilterView());
		dataProvider.addDataDisplay(view.getDataDisplay());
	}

	public void onStop()
	{
		dataProvider.removeDataDisplay(view.getDataDisplay());
	}
	@Override
	public void onNewSong()
	{
		placeController.goTo(new EditPlace(activityModul.getSongActivityId()));
		
	}

	@Override
	public void onEdit(SongProxy song)
	{
		if(song!=null)
		{
			EditPlace p = new EditPlace(activityModul.getSongActivityId());
			p.setId(song.getId());
			placeController.goTo(p);
		}
	}
	@Override
	public void onDelete(SongProxy song)
	{
		serviceProvider.getSongService().delete(song).fire(new Receiver<Void>()
		{

			@Override
			public void onSuccess(Void v)
			{
				dataProvider = new DataProvider(view.getFilterView());
				dataProvider.addDataDisplay(view.getDataDisplay());
			}

		});
	}
	
	private class DataProvider extends AsyncDataProvider<SongProxy> implements
			IFetcher<SongProxy>, IDataUpdater<SongProxy>
	{
		private final ISongFilterView filterView;
		private final BufferedDataProvider<SongProxy> buffer = new BufferedDataProvider<SongProxy>();
		
		public DataProvider(ISongFilterView filterView)
		{
			this.filterView = filterView;
			buffer.setFetcher(this);
			buffer.setUpdater(this);
			buffer.setFilter(new Filter(filterView));
		}

		public void clear()
		{
			buffer.clear();
		}

		@Override
		protected void onRangeChanged(HasData<SongProxy> display)
		{
			buffer.onRangeChange(display, currentSortInfo);
		}

		@Override
		public void fetch(Range range, ISortInfo sortInfo,
				Receiver<List<SongProxy>> receiver)
		{
			SimpleSortInfo simpleSortInfo = (SimpleSortInfo) sortInfo;
			SongServiceRequest serviceRequest = serviceProvider
					.getSongService();
			SongFilterProxy filter = serviceRequest.create(SongFilterProxy.class);
			filter.setField(filterView.getField());
			filter.setValue(filterView.getValue());
			filter.setSortField(simpleSortInfo == null ? "" : simpleSortInfo
					.getFieldName());
			filter.setAscending(simpleSortInfo == null ? true : simpleSortInfo
					.isAscending());
			serviceRequest.findByFilter(filter, range.getStart(),
					range.getLength()).fire(receiver);
		}
		
		
	}

	private static class Filter
	{
		ISongFilterView filterView;

		public Filter(ISongFilterView filterView)
		{
			super();
			this.filterView = filterView;
		}

		@Override
		public int hashCode()
		{
			String value = filterView.getValue();
			FilterField field = filterView.getField();
			final int prime = 31;
			int result = 1;
			result = prime * result + ((field == null) ? 0 : field.hashCode());
			result = prime * result + ((value == null) ? 0 : value.hashCode());
			return result;
		}

	}

	@Override
	public void onSearch()
	{
		view.clearSongSelection();
		view.getDataDisplay().setVisibleRangeAndClearData(
				new Range(0, viewSize),
				true);
	}

	@Override
	public void update(SongEditColumn column, final int index,
			SongProxy object, String value)
	{
		if (!column.getValue(object).equals(value))
		{
			SongServiceRequest serviceRequest = serviceProvider
					.getSongService();
			Receiver<SongProxy> receiver = new Receiver<SongProxy>()
			{
				@Override
				public void onSuccess(SongProxy response)
				{
					dataProvider.clear();
					dataProvider.onRangeChanged(view.getDataDisplay());
				}
			};
			if ("number".equals(column.getFieldName()))
			{
				serviceRequest.updateNumber(object, Integer.parseInt(value))
						.fire(receiver);
			}
			else
			{
				SongProxy editSong = serviceRequest.edit(object);
				column.setValue(editSong, value);
				serviceRequest.save(editSong).fire(receiver);
			}
		}

	}

	@Override
	public void onColumnSort(ColumnSortEvent event)
	{
		ColumnSortInfo sortInfo = event.getColumnSortList().get(0);
		SortableColumn column = (SortableColumn) sortInfo.getColumn();
		currentSortInfo = new SimpleSortInfo(
				column.getFieldName(), sortInfo.isAscending());
		dataProvider.buffer.onSort(view.getDataDisplay(), currentSortInfo);
	}

}
